#include "paintarea.h"
#include <QPainter>
#include <QGridLayout>
#include "net.h"
#include "data_struct.h"

PaintArea::PaintArea(QWidget *parent) : QWidget(parent)
{
    int i;
    mCenter[0] = QPoint(380, 410);//NUDT
    mCenter[1] = QPoint(460, 300);//SU
    mCenter[2] = QPoint(470, 310);//NUAA
    mCenter[3] = QPoint(430, 220);//ICT
    mCenter[4] = QPoint(290, 370);//UESTC
    mCenter[5] = QPoint(475, 320);//LGDX
    mCenter[6] = QPoint(300, 380);//30

    for(i=0; i<7; i++) {
        mColors[i] = Qt::black;
        displayLabel[i] = new QLabel(tr("EGP_ID: %1\n").arg(i+1) + mNormalMessage);
    }

    mUdpSocket.bind(PORT_WITH_PRESENTATION);
    connect(&mUdpSocket, SIGNAL(readyRead()), SLOT(onProcessPendingDatagrams()));

    picLabel = new QLabel;
    picLabel->setFixedSize(600, 800);
    QGridLayout *mainLayout = new QGridLayout;
    mainLayout->addWidget(picLabel, 0, 0, 7, 1);
    for(i=0; i<7; i++) {
        mainLayout->addWidget(displayLabel[i], i, 1, 1, 1);
    }
    setLayout(mainLayout);
    this->setFixedSize(800, 800);

    for(i=0; i<7; i++){
        updateLastAlertTime[i] = true;
        gettimeofday(&mLastAlertTime[i], NULL);
    }
}

PaintArea::~PaintArea() {

}

void PaintArea::paintEvent(QPaintEvent *p) {
    QPainter painter(this);

    QPen pen;
    int i;
    QPixmap mypix;
    mypix.load("./pic.png");
    painter.drawPixmap(0,0,580,550,mypix);
    for(i=0; i<7; i++) {
        pen.setColor(mColors[i]);
        painter.setPen(pen);
        painter.drawEllipse(mCenter[i], 8, 8);
        painter.drawText(QRectF(mCenter[i].x()-5, mCenter[i].y()-5, 10, 10), Qt::AlignCenter, QString("%1").arg(i+1));
    }
}

void PaintArea::setColors(int index, QColor c) {
    this->mColors[index] = c;
}

void PaintArea::onProcessPendingDatagrams() {
    QByteArray datagram;
    while(mUdpSocket.hasPendingDatagrams()) {
        printf("recv a packet!\n");
        datagram.resize(mUdpSocket.pendingDatagramSize());
        mUdpSocket.readDatagram(datagram.data(), datagram.size());
    }
    char *recvBuffer = datagram.data();
    unsigned char protocolType;
    memcpy(&protocolType, recvBuffer+4, 1);

    int EGP_ID;

    if(ALERT_TYPE == protocolType) {
//        //this->setColors(0, Qt::red);
//        printf("deal with ALERT!\n");
//        ALERT_PACKET alertPkt;
//        unsigned char portStatus;
//        decode_alert_packet(&alertPkt, (unsigned char*)recvBuffer);
//        EGP_ID = alertPkt.EGP_ID;
//        portStatus = alertPkt.port_status;

//        int i;

//        for(i=0; i<8; i++) {
//            if((portStatus & (1<<i)) != 0) {
//                gettimeofday(&mLastAlertTime[EGP_ID-1], NULL);
//                break;
//            }
//        }

//        QString portMessage = "";
//        for(i=0; i<8; i++) {
//            if((portStatus & (1<<i)) != 0) {
//                portMessage += tr("%1 ").arg(i);
//            }
//        }
//        displayLabel[EGP_ID-1]->setText(tr("EGP_ID: %1\n").arg(EGP_ID) + tr("port:") + portMessage + mAlertMessage);

//        this->setColors(EGP_ID-1, Qt::red);
//        this->update();
    } else if(ALERT_CANCEL_TYPE == protocolType) {
        printf("deal with ALERT_CANCEL!\n");
        ALERT_CANCEL_PACKET alertCancelPkt;
        decode_alert_cancel_packet(&alertCancelPkt, (unsigned char*)recvBuffer);
        EGP_ID = alertCancelPkt.EGP_ID;
        if(updateLastAlertTime[EGP_ID-1]==false){//attack exist, otherwise noting should be cancel
            updateLastAlertTime[EGP_ID-1]=true;//this attack end, permit record next attack start time
            int elapsedMs;
            struct timeval before = mLastAlertTime[EGP_ID-1];
            gettimeofday(&mLastAlertTime[EGP_ID-1], NULL);
            elapsedMs = (mLastAlertTime[EGP_ID-1].tv_sec-before.tv_sec)*1000 + (mLastAlertTime[EGP_ID-1].tv_usec-before.tv_usec)/1000;
        //    elapsedMs -= 5000;
            if(elapsedMs>0){
                printf("elapsed = %d ms\n", elapsedMs);
                long dropPackets = alertCancelPkt.dropPackets;
                displayLabel[EGP_ID-1]->setText(tr("EGP_ID: %1\n").arg(EGP_ID) + mNormalMessage + "\n" + tr("elapsed time = %1 ms\n").arg(elapsedMs)
                                                +tr("drop packets: %1\n").arg(dropPackets));
                this->setColors(EGP_ID-1, Qt::black);
                this->update();
            }else{
                displayLabel[EGP_ID-1]->setText(tr("EGP_ID: %1\n").arg(EGP_ID) + mNormalMessage + "\n");
                this->setColors(EGP_ID-1, Qt::black);
                this->update();
            }
        }

    } else if(ATTACK_TYPE == protocolType){

        //deal with attack type
        printf("deal with ATTACK_TYPE!\n");
        ATRACT_TYPE atractTypePacket;
        decode_atract_type_packet(&atractTypePacket, (unsigned char*)recvBuffer);
        char attackType = atractTypePacket.type;
        EGP_ID = atractTypePacket.EGP_ID;
        QString t = QString("EGP_ID: %1\n").arg(EGP_ID);
//        switch (EGP_ID) {
//        case 1:
//            t += "EGP_ID: 1\n";
//            break;
//        case 2:
//            t += "EGP_ID: 2\n";
//            break;
//        case 3:
//            t += "EGP_ID: 3\n";
//            break;
//        case 4:
//            t += "EGP_ID: 4\n";
//            break;
//        case 5:
//            t += "EGP_ID: 5\n";
//            break;
//        case 6:
//            t += "EGP_ID: 6\n";
//            break;
//        case 7:
//            t += "EGP_ID: 7\n";
//            break;
//        default:
//            break;
//        }

        t += "\nAttack Type: ";

        if((attackType & (1<<0)) != 0) {
           t += "TCP SYN Flood\n";
        }
        if((attackType & (1<<1)) != 0) {
           t += "UDP Flood\n";
        }
        if((attackType & (1<<2)) != 0) {
           t += "ICMP Flood\n";
        }
        if((attackType & (1<<3)) != 0) {
           t += "Smurf\n";
        }
        if((attackType & (1<<4)) != 0) {
           t += "Fraggle\n";
        }
        if((attackType & (1<<5)) != 0) {
           t += "Land\n";
        }

        displayLabel[EGP_ID-1]->setText(t);

//        //deal with alert
        printf("deal with ALERT!\n");
        if(updateLastAlertTime[EGP_ID-1] == true){
            gettimeofday(&mLastAlertTime[EGP_ID-1], NULL);
            updateLastAlertTime[EGP_ID-1] = false;//no longer update, keep attack start time
        }

        this->setColors(EGP_ID-1, Qt::red);
        this->update();
    }
}
